package top.jfunc.json.utils;

import top.jfunc.json.Json;
import top.jfunc.json.annotation.JsonField;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author xiongshiyan at 2019/3/15 , contact me with email yanshixiong@126.com or phone 15208384257
 */
public class JsonUtil {
    @SuppressWarnings("unchecked")
    public static void appendValue(StringBuilder sb, Object value , boolean nullHold) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        if(null == value){
            if(nullHold){
                sb.append("null");
            }
        }else if (value instanceof Json) {
            sb.append(value.toString());
        } else if (isNoQuote(value)) {
            sb.append(value);
        } else if (isQuote(value)) {
            sb.append("\"").append(value).append("\"");
        } else if (value instanceof Date) {
            sb.append("\"").append(formatter.format(value)).append("\"");
        } else if (value.getClass().isArray()) {
            sb.append(arrayToStr(value));
        } else if (value instanceof List) {
            sb.append(listToStr((List<Object>) value));
        } else if (value instanceof Map) {
            sb.append(mapToStr((Map<String, Object>) value));
        } else {
            //JavaBean风格
            sb.append(mapToStr(bean2Map(value , nullHold)));
        }
    }
    public static String mapToStr(Map<String , Object> map) {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object value = entry.getValue();
            /*if (value == null) {
                continue;// 对于null值，不进行处理，页面上的js取不到值时也是null
            }*/
            sb.append("\"").append(entry.getKey()).append("\":");
            JsonUtil.appendValue(sb, value , true);
            sb.append(",");
        }
        int len = sb.length();
        if (len > 2) {
            sb.delete(len - 1, len);
        }
        sb.append("}");
        return sb.toString();
    }
    @SuppressWarnings("unchecked")
    public static String arrayToStr(Object array) {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        int len = Array.getLength(array);
        Object value = null;
        for (int i = 0; i < len; i++) {
            value = Array.get(array, i);
            appendValue(sb , value , true);
            sb.append(",");
        }
        len = sb.length();
        if (len > 2) {
            sb.delete(len - 1, len);
        }
        sb.append("]");
        return sb.toString();
    }

    @SuppressWarnings("unchecked")
    public static String listToStr(List<Object> list) {
        if (list == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        Object value = null;
        for (Iterator<Object> it = list.iterator(); it.hasNext();) {
            value = it.next();
            appendValue(sb , value , true);
            sb.append(",");
        }
        int len = sb.length();
        if (len > 1) {
            sb.delete(len - 1, len);
        }
        sb.append("]");
        return sb.toString();
    }
    /**
     * 从一个bean装载数据，返回一个 JSONObject 对象。 <br/>
     */
    @SuppressWarnings("unchecked")
    public static Map<String , Object> bean2Map(Object bean , boolean nullHold, String... ignoreFields) {
        Map<String , Object> map = new HashMap<>();
        if (bean == null) {
            return map;
        }
        Class cls = bean.getClass();
        Field[] fs = cls.getDeclaredFields();
        Object value = null;
        String fieldName = null;
        Method method = null;
        int len = fs.length;
        for (int i = 0; i < len; i++) {

            Field field = fs[i];
            fieldName = field.getName();
            try {
                method = cls.getMethod(getGetter(fieldName), (Class[]) null);
                value = method.invoke(bean, (Object[]) null);
            } catch (Exception e) {
                continue;
            }

            if(null == value && !nullHold){
                continue;
            }

            if(field.isAnnotationPresent(JsonField.class)){
                JsonField annotation = field.getAnnotation(JsonField.class);
                //不序列化此字段
                if(!annotation.serialize()){
                    continue;
                }

                fieldName = annotation.value();
            }

            //未被忽略的字段
            if(!targetInArray(ignoreFields , fieldName)){
                map.put(fieldName, value);
            }
        }
        return map;
    }
    private static String getGetter(String property) {
        return "get" + property.substring(0, 1).toUpperCase()
                + property.substring(1, property.length());
    }

    /**
     * 检查某个值是否在数组中
     */
    public static <T> boolean targetInArray(T[] array, T target) {
        if(null == array || array.length == 0){
            return false;
        }
        for (T s : array) {
            if(s.equals(target)){
                return true;
            }
        }
        return false;
    }
    /**
     * 判断是否要加引号
     */
    private static boolean isNoQuote(Object value) {
        return (value.getClass().isPrimitive() || Number.class.isAssignableFrom(value.getClass()) || value instanceof Boolean );
    }
    private static boolean isQuote(Object value) {
        return (value instanceof String || value instanceof Character);
    }

}
